using Microsoft.VisualStudio.TestTools.UnitTesting;
using StockholmsStad.Data.Interfaces;
using StockholmsStad.Runtime.Serialization.DataContract;
using StockholmsStad.Runtime.Serialization.DataContract.Enums;

namespace StockholmsStad.Data.Test
{
    /// <summary>
    /// Testar CRUD för Persontabellen och Addresstabellen
    /// </summary>
    [TestClass]
    public class TestUnitPerson : TestUnitBase
    {
        // before running each test 
        [TestInitialize()]
        public void MyTestInitialize()
        {
            BeginTransaction();
        }

        // after each test has run
        [TestCleanup()]
        public void MyTestCleanup()
        {
            EndTransaction();
        }

        [TestMethod]
        public void InsertAndRetrievePerson1()
        {
            IPersonAgent agent = AgentFactory.GetPersonAgent();
            Person person1 = TestEntity.GetNewPerson1();
            int personId = agent.AddPerson(context, person1);
            person1.PersonId = personId;

            Assert.AreNotEqual(0, personId, "Person added error");

            Person retrievedPerson = agent.GetPerson(context, personId);

            ArePersonEqual(person1, retrievedPerson);
            AreAddressEqual(person1.Address, retrievedPerson.Address);
        }

        [TestMethod]
        public void InsertAndRetrievePerson2()
        {
            IPersonAgent agent = AgentFactory.GetPersonAgent();
            Person person2 = TestEntity.GetNewPerson2();
            person2.Address = TestEntity.GetNewAddress();
            int personId = agent.AddPerson(context, person2);
            person2.PersonId = personId;

            Assert.AreNotEqual(0, personId, "Person added error");

            Person retrievedPerson = agent.GetPerson(context, personId);

            ArePersonEqual(person2, retrievedPerson);
            Assert.IsNotNull(person2.Address, "Address is not null");
            Assert.IsNotNull(retrievedPerson.Address, "Address is not null");
        }

        [TestMethod]
        public void UpdatePerson()
        {
            IPersonAgent agent = AgentFactory.GetPersonAgent();
            Person person1 = TestEntity.GetNewPerson1();
            int personId = agent.AddPerson(context, person1);
            person1.PersonId = personId;
            person1.Address = null;

            Assert.AreNotEqual(0, personId, "Person added error");

            Person retrievedPerson = agent.GetPerson(context, personId);
            ArePersonEqual(person1, retrievedPerson);
            Assert.IsNull(person1.Address, "Address is not null");

            person1.FirstNames = "UpdateFirstName";
            person1.Address = TestEntity.GetNewAddress();
            person1.Email = "update@sdfsdf.se";
            person1.LastName = "UpdateLastName";
            person1.Nationality = "UpDatenat";
            person1.PersonalNumber = "12345678";
            person1.PhoneNumber = "update";
            person1.Sex = Sex.Female;
            person1.SwedishNationality = false;
            agent.UpdatePerson(context, personId, person1);
            retrievedPerson = agent.GetPerson(context, personId);
            ArePersonEqual(person1, retrievedPerson);
            Assert.IsNotNull(retrievedPerson.Address, "Address is not null");
        }

        [TestMethod]
        public void UpdateContactPerson()
        {
            IPersonAgent agent = AgentFactory.GetPersonAgent();
            ContactPerson person1 = TestEntity.GetNewContactPerson();
            int? personId = agent.AddPerson(context, person1);

            Assert.AreNotEqual(0, personId, "ContactPerson added error");

            ContactPerson retrievedPerson = agent.GetPerson(context, personId);
            AreContactEqual(person1, retrievedPerson);

            person1.FirstNames = "UpdateFirstName";
            person1.Email = "update@sdfsdf.se";
            person1.LastName = "UpdateLastName";
            agent.UpdatePerson(context, personId, person1);
            retrievedPerson = agent.GetPerson(context, personId);
            AreContactEqual(person1, retrievedPerson);
        }

        [TestMethod]
        public void UpdateContactPerson2()
        {
            IPersonAgent agent = AgentFactory.GetPersonAgent();
            int? personId = null;

            Assert.AreNotEqual(0, personId, "ContactPerson added error");

            ContactPerson retrievedPerson = agent.GetPerson(context, personId);
            Assert.IsNull(retrievedPerson);
            ContactPerson person1 = TestEntity.GetNewContactPerson();
            person1.FirstNames = "UpdateFirstName";
            person1.Email = "update@sdfsdf.se";
            person1.LastName = "UpdateLastName";
            personId = agent.UpdatePerson(context, personId, person1);
            retrievedPerson = agent.GetPerson(context, personId);
            AreContactEqual(person1, retrievedPerson);
        }

        [TestMethod]
        public void UpdateContactPerson3()
        {
            IPersonAgent agent = AgentFactory.GetPersonAgent();
            int? personId = null;

            Assert.AreNotEqual(0, personId, "ContactPerson added error");

            ContactPerson retrievedPerson = agent.GetPerson(context, personId);
            Assert.IsNull(retrievedPerson);
            personId = agent.UpdatePerson(context, personId, null);
            retrievedPerson = agent.GetPerson(context, personId);
            Assert.IsNull(retrievedPerson);
        }

        [TestMethod]
        public void UpdateContactPerson4()
        {
            IPersonAgent agent = AgentFactory.GetPersonAgent();
            ContactPerson contactPerson = TestEntity.GetNewContactPerson();
            int? personId = agent.AddPerson(context, contactPerson);

            Assert.AreNotEqual(0, personId, "ContactPerson added error");

            ContactPerson retrievedPerson = agent.GetPerson(context, personId);
            AreContactEqual(contactPerson, retrievedPerson);

            agent.UpdatePerson(context, personId, null);
            retrievedPerson = agent.GetPerson(context, personId);

            // Tyvärr kan det här testet inte verifieras eftersom borttagning av kontaktperson
            // inte submittas av den här metoden utan av couple-update.
            //Assert.IsNull(retrievedPerson);
        }

        public static void ArePersonEqual(Person expectedPerson, Person retrievedPerson)
        {
            Assert.AreEqual(expectedPerson.PersonId, retrievedPerson.PersonId,
                            string.Format("Retrieved PersonId ({0}) not the same as expected PersonId ({1})",
                                          expectedPerson.PersonId, retrievedPerson.PersonId));
            Assert.AreEqual(expectedPerson.FirstNames, retrievedPerson.FirstNames,
                            string.Format("Retrieved FirstNames ({0}) not the same as expected FirstNames ({1})",
                                          expectedPerson.FirstNames, retrievedPerson.FirstNames));
            Assert.AreEqual(expectedPerson.LastName, retrievedPerson.LastName,
                            string.Format("Retrieved LastName ({0}) not the same as expected LastName ({1})",
                                          expectedPerson.LastName, retrievedPerson.LastName));
            Assert.AreEqual(expectedPerson.PersonalNumber, retrievedPerson.PersonalNumber,
                            string.Format(
                                "Retrieved PersonalNumber ({0}) not the same as expected PersonalNumber ({1})",
                                expectedPerson.PersonalNumber, retrievedPerson.PersonalNumber));

            if (!retrievedPerson.Nationality.Equals("Svenskt"))
                Assert.AreEqual(expectedPerson.Nationality, retrievedPerson.Nationality,
                                string.Format("Retrieved Nationality ({0}) not the same as expected Nationality ({1})",
                                              expectedPerson.Nationality, retrievedPerson.Nationality));

            Assert.AreEqual(expectedPerson.SwedishNationality, retrievedPerson.SwedishNationality,
                            string.Format(
                                "Retrieved SwedishNationality ({0}) not the same as expected SwedishNationality ({1})",
                                expectedPerson.SwedishNationality, retrievedPerson.SwedishNationality));
            Assert.AreEqual(expectedPerson.ProtectedIdentity, retrievedPerson.ProtectedIdentity,
                            string.Format(
                                "Retrieved ProtectedIdentity ({0}) not the same as expected ProtectedIdentity ({1})",
                                expectedPerson.ProtectedIdentity, retrievedPerson.ProtectedIdentity));
            Assert.AreEqual(expectedPerson.PhoneNumber, retrievedPerson.PhoneNumber,
                            string.Format("Retrieved Phonenumber ({0}) not the same as expected Phonenumber ({1})",
                                          expectedPerson.PhoneNumber, retrievedPerson.PhoneNumber));
            Assert.AreEqual(expectedPerson.Email, retrievedPerson.Email,
                            string.Format("Retrieved Phonenumber ({0}) not the same as expected Phonenumber ({1})",
                                          expectedPerson.Email, retrievedPerson.Email));
            Assert.AreEqual(expectedPerson.Sex, retrievedPerson.Sex,
                            string.Format("Retrieved Sex ({0}) not the same as expected Sex ({1})", expectedPerson.Sex,
                                          retrievedPerson.Sex));
        }

        public static void AreAddressEqual(Address expectedAddress, Address retrievedAddress)
        {
            Assert.AreEqual(expectedAddress.City, retrievedAddress.City,
                            string.Format("Retrieved city ({0}) not the same as expected city ({1})",
                                          expectedAddress.City, retrievedAddress.City));
            Assert.AreEqual(expectedAddress.CoAddress, retrievedAddress.CoAddress,
                            string.Format("Retrieved CoAddress ({0}) not the same as expected CoAddress ({1})",
                                          expectedAddress.City, retrievedAddress.City));
            Assert.AreEqual(expectedAddress.Country, retrievedAddress.Country,
                            string.Format("Retrieved Country ({0}) not the same as expected Country ({1})",
                                          expectedAddress.City, retrievedAddress.City));
            Assert.AreEqual(expectedAddress.PostCode, retrievedAddress.PostCode,
                            string.Format("Retrieved PostCode ({0}) not the same as expected PostCode ({1})",
                                          expectedAddress.City, retrievedAddress.City));
            Assert.AreEqual(expectedAddress.StreetAddress, retrievedAddress.StreetAddress,
                            string.Format("Retrieved StreetAddress ({0}) not the same as expected StreetAddress ({1})",
                                          expectedAddress.City, retrievedAddress.City));
        }

        public static void AreContactEqual(ContactPerson expectedPerson, ContactPerson retrievedPerson)
        {
            Assert.AreEqual(expectedPerson.Email, retrievedPerson.Email,
                            string.Format("Retrieved Email ({0}) not the same as expected Email ({1})",
                                          expectedPerson.Email, retrievedPerson.Email));
            Assert.AreEqual(expectedPerson.FirstNames, retrievedPerson.FirstNames,
                            string.Format("Retrieved FirstNames ({0}) not the same as expected FirstNames ({1})",
                                          expectedPerson.FirstNames, retrievedPerson.FirstNames));
            Assert.AreEqual(expectedPerson.LastName, retrievedPerson.LastName,
                            string.Format("Retrieved LastName ({0}) not the same as expected LastName ({1})",
                                          expectedPerson.LastName, retrievedPerson.LastName));
            Assert.AreEqual(expectedPerson.Telephone, retrievedPerson.Telephone,
                            string.Format("Retrieved Telephone ({0}) not the same as expected Telephone ({1})",
                                          expectedPerson.Telephone, retrievedPerson.Telephone));
        }

    }
}